<?php
class CMemcacheSession extends CSession
{
	static $memcacheObject;
	private static $timeout = 1200;
	public $id;
	private $data;
	private static $sessions;

	/**
	 * Constructor
	 *
	 */
	function __construct() {
		session_set_save_handler(array($this, 'sessionOpen'),
                             array($this, 'sessionClose'),
                             array($this, 'sessionRead'),
                             array($this, 'sessionWrite'),
                             array($this, 'sessionDestroy'),
                             array($this, 'sessionGC'));
    self::initCache();
    session_start();
    $this->id = session_id();
    if (!isset($_COOKIE['PHPSESSID']) || $_COOKIE['PHPSESSID']!=session_id()) {
    	while ($this->data = self::$memcacheObject->get($this->id)) {
    		error_log(@$_COOKIE['PHPSESSID'] . ' ' . session_id() . "\n", 3,  ROOT_DIR.'publish/dup-login.txt');
    		session_regenerate_id();
    		$this->id = session_id();
    	}
    }
		setcookie('PHPSESSID', $this->id, 0, '/', COOKIE_URL);
	}

	/**
	 * Get session attribute
	 *
	 * @param string $name
	 * @return attribute
	 */
	function get($name) {
		return @$_SESSION[$name];
	}

	/**
	 * Set session attribute
	 *
	 * @param string $name
	 * @param mixed $value attribute value
	 */
	function set($name, $value) {
		$_SESSION[$name] = $value;
	}

	/**
	 * Enter description here...
	 *
	 * @param unknown_type $name
	 */
	function delete($name) {
		unset($_SESSION[$name]);
	}

	/**
	 * Enter description here...
	 *
	 */
	function close() {
	}

	/**
   * Init cache object
   *
   */
  public static function initCache() {
    if (null == self::$memcacheObject) {
      self::$memcacheObject = CSystem::$cachesession;
    }
  }

  /**
   * Open a session.
   *
   * @param string
   * @param string
   *
   * @return bool true, if the session was opened, otherwise an exception is
   *              thrown.
   * @throws sfInitializationException If process cache functions cannot be used
   */
  public function sessionOpen($path, $name) {
    // Check that process cache is enabled
  }


  /**
   * Read a session.
   *
   * @param string A session ID.
   *
   * @return data from cache if the session was read else returns string empty
   *
   */
  public function sessionRead($id) {
    // Read
    return self::$memcacheObject->get($id, '');
  }

  /**
   * Write session data.
   *
   * @param string A session ID.
   * @param string A serialized chunk of session data.
   *
   * @return bool true, if the session was written, otherwise an exception is
   *              thrown.
   *
   */
  public function sessionWrite($id, $data) {
    $sessions = self::getSessions(true);
    $this->sessionInfo($sessInfo);
    $sessions[$id] = $sessInfo;
    self::saveSessions($sessions);
    if ($data!=null)
    	self::$memcacheObject->set($id, $data, self::$timeout);
    return true;
  }

  public function sessionInfo(&$info) {
  	if ($info==null) {
  		$info = array();
	  	$user = $this->get('user');
  	} else {
  		if (!isset($info[1]) && user()->is_login()) {
  			$user = $this->get('user');
  		}
  	}
  	if (isset($user) && $user->is_login()) {
  		$info[1] = $user->data['id'];
  		$info[2] = $user->data['full_name'];
//  		$info[3] = $user->data['total_point'];
//  		$info[4] = $user->data['avatar_url'];
//  		$info[5] = $user->data['blast'];
//  		if ($info[6] = $user->data['is_register_salesman']) {
//  			$info[7] = $user->data['start_time'];
//  		}
  		$info[8] = $user->data['ym'];
  	}
  	$info[0] = time();
  	if ($estore_id = @$_REQUEST['estore_id']) {
  		$info['estore'.$estore_id] = time();
  	}
  	return $info;
  }

 /**
  * Close a session.
  *
  * @return bool true, if the session was closed, otherwise false.
  */
  public function sessionClose() {
    return true;
  }

  /**
   * Destroy a session.
   * @param string A session ID.
   * @return bool true, if the session was destroyed
   */
  public function sessionDestroy($id) {
    // delete the record associated with this id
    $sessions = self::getSessions(true);
    unset($sessions[$id]);
    self::saveSessions($sessions);
    self::$memcacheObject->delete($id);
    return true;
  }

  /**
   * Cleanup old sessions.
   * @param int The lifetime of a session.
   */
  public function sessionGC($lifetime) {
    return true; // Garbage collection happens automatically in memcache
  }

  /**
   * Get sessions from cache
   *
   * @return unknown
   */
  public static function &getCacheSessions() {
  	if (self::$sessions) return self::$sessions;
  	self::initCache();
  	self::$sessions = self::$memcacheObject->get('sessions', array());
  	return self::$sessions;
  }

  static $already_save_sessions = false;

  /**
   * Get list of session
   *
   * @param boolean $removeOldSession =true: remove timeout session
   * @return array of session_id
   */
  public static function &getSessions($removeOldSession = false) {
    $sessions = &self::getCacheSessions();
    if ($removeOldSession) {
      $time = time();
      if (isset($estore_id)) {
      	// estore sessions
      	foreach ($sessions as $key=>$value)
      		if ($value[0] + self::$timeout < $time) {
	      		unset($sessions[$key]);
	      	} else {

	      	}
      } else {
      	// sessions
	      foreach ($sessions as $key=>$value)
	      	if ($value[0] + self::$timeout < $time) {
	      		if (isset($value[6]) && $value[6]) {
		      		$time = $value[0] - $value[7];
		      		if ($time>0) {
		      			require_once(ROOT_DIR.'/lib/models/CSalesActivity.php');
		      			new CSalesActivity($value[1], null, $time, 0, 0, $value[7]);
		      		}
	      		}
	      		unset($sessions[$key]);
	      		$need_save = true;
	      	}
      }
    }
    return self::$sessions;
  }

  /**
   * Remove previous user sessions
   *
   * @param unknown_type $user_id
   */
  public static function removePreviousLogin($user_id) {
  	$sessions = &self::getCacheSessions();
  	foreach ($sessions as $key=>$value) {
  		if (@$value[1] == $user_id) {
  			unset($sessions[$key]);
  			self::$memcacheObject->delete($key);
  			break;
  		}
  	}
  }

  /**
   * Save list session
   *
   * @param array $sessions
   */
  public static function saveSessions($sessions) {
    self::initCache();
    self::$memcacheObject->set('sessions', $sessions, 864000);
  }

  private static $nGuests;
  private static $nUsers;
  private static $onlineBuyers;
  private static $onlineSellers;
  private static $isOnlines;

  /**
   * Get online users status
   *
   */
  private static function getOnlineUsers() {
  	if (isset(self::$nGuests) && isset(self::$nUsers) && isset(self::$onlineBuyers) && isset(self::$onlineSellers)) return;
  	self::initCache();
  	self::$nGuests = 0;
  	self::$nUsers = 0;
  	self::$onlineBuyers = array();
  	self::$onlineSellers = array();
  	self::$isOnlines = array();
  	$sesses = self::getSessions(true);

  	//var_dump($_REQUEST); exit();
  	if ($estore_id = @$_REQUEST['estore_id']) {
  		// for estore
  		$estore_id = 'estore'.$estore_id;
  		foreach ($sesses as &$value) {
  			self::$isOnlines[$value[1]] = 1;
  			if (!isset($value[$estore_id])) continue;
	  		if (isset($value[1])) {
	  			// is user
	  			self::$nUsers++;
	  			if ($value[6] == 2) {
	  				self::$onlineSellers[] = $value;
	  			} else {
	  				self::$onlineBuyers[] = $value;
	  			}
	  		} else {
	  			// is guest
	  			self::$nGuests++;
	  		}
	  	}
  	} else {
  		// for
	  	foreach ($sesses as &$value) {
	  		if (isset($value[1])) {
	  			// is user
	  			self::$nUsers++;
	  			self::$isOnlines[$value[1]] = 1;
	  			if ($value[6] == 2) {
	  				self::$onlineSellers[] = $value;
	  			} else {
	  				self::$onlineBuyers[] = $value;
	  			}
	  		} else {
	  			// is guest
	  			self::$nGuests++;
	  		}
	  	}
  	}
  }

  public static function getOnlineSellers() {
  	self::getOnlineUsers();
  	return self::$onlineSellers;
  }

  public static function getOnlineBuyers() {
  	self::getOnlineUsers();
  	return self::$onlineBuyers;
  }

  public static function getNumberOfGuest() {
  	return self::$nGuests;
  }

  public static function getNumberOfUsers() {
  	return self::$nUsers;
  }

  public static function isOnline($user_id) {
  	self::getOnlineUsers();
  	return isset(self::$isOnlines[$user_id]);
  }
}